package ms.jasim.console.gui.component;

import java.awt.BorderLayout;
import java.awt.Font;
import java.util.HashMap;
import java.util.Map;

import javax.swing.DefaultListModel;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SpringLayout;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

import ms.jacrim.pddl.PddlSolution;
import ms.jasim.framework.PddlModel;
import ms.spm.IAppContext;
import ms.utils.Event;
import ms.utils.NamedList;

public class MP_SolutionPanel extends JPanel {

	private JTextArea txtSolution;
	private JTable tblEvaluator;
	private JList lbSolutions;
	private static final long serialVersionUID = 1L;

	public IAppContext Context;
	private DefaultListModel lbSolutionModel;
	private NamedList<PddlSolution> solutions;
	private DefaultTableModel tblEvaluatorModel;
	private Map<PddlSolution, Object[]> solutionData = new HashMap<PddlSolution, Object[]>();
	private SimulationTimelinePanel simulationTimelinePanel;
	private PddlModel model; 
	
	/**
	 * Create the panel
	 */
	public MP_SolutionPanel() {
		super();
		setLayout(new BorderLayout());

		final JSplitPane splitPane = new JSplitPane();
		splitPane.setBorder(new EmptyBorder(0, 0, 0, 0));
		splitPane.setDividerSize(4);
		splitPane.setResizeWeight(0.3);
		add(splitPane, BorderLayout.CENTER);

		final JPanel panel_3 = new JPanel();
		panel_3.setBorder(new EmptyBorder(0, 0, 0, 0));
		final SpringLayout springLayout = new SpringLayout();
		panel_3.setLayout(springLayout);
		splitPane.setLeftComponent(panel_3);

		final JLabel solutionFilesLabel = new JLabel();
		solutionFilesLabel.setText("Available Solutions");
		panel_3.add(solutionFilesLabel);
		springLayout.putConstraint(SpringLayout.SOUTH, solutionFilesLabel, 25, SpringLayout.NORTH, panel_3);
		springLayout.putConstraint(SpringLayout.NORTH, solutionFilesLabel, 9, SpringLayout.NORTH, panel_3);
		springLayout.putConstraint(SpringLayout.WEST, solutionFilesLabel, 5, SpringLayout.WEST, panel_3);

		final JScrollPane scrollPane = new JScrollPane();
		panel_3.add(scrollPane);
		springLayout.putConstraint(SpringLayout.SOUTH, scrollPane, -6, SpringLayout.SOUTH, panel_3);
		springLayout.putConstraint(SpringLayout.NORTH, scrollPane, 5, SpringLayout.SOUTH, solutionFilesLabel);
		springLayout.putConstraint(SpringLayout.EAST, scrollPane, -5, SpringLayout.EAST, panel_3);
		springLayout.putConstraint(SpringLayout.WEST, scrollPane, 5, SpringLayout.WEST, panel_3);

		lbSolutions = new JList();
		lbSolutions.addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(final ListSelectionEvent e) {
				updateSolutionListSelection();
			}
		});
		lbSolutionModel = new DefaultListModel();
		lbSolutions.setModel(lbSolutionModel);		
		scrollPane.setViewportView(lbSolutions);

		final JPanel panel_4 = new JPanel();
		panel_4.setBorder(new EmptyBorder(0, 0, 0, 0));
		final SpringLayout springLayout_1 = new SpringLayout();
		panel_4.setLayout(springLayout_1);
		splitPane.setRightComponent(panel_4);

		final JScrollPane scrollPane_2 = new JScrollPane();
		panel_4.add(scrollPane_2);
		springLayout_1.putConstraint(SpringLayout.SOUTH, scrollPane_2, 80, SpringLayout.NORTH, panel_4);
		springLayout_1.putConstraint(SpringLayout.NORTH, scrollPane_2, 5, SpringLayout.NORTH, panel_4);
		springLayout_1.putConstraint(SpringLayout.EAST, scrollPane_2, -11, SpringLayout.EAST, panel_4);
		springLayout_1.putConstraint(SpringLayout.WEST, scrollPane_2, 5, SpringLayout.WEST, panel_4);

		tblEvaluator = new JTable();
		tblEvaluatorModel = new DefaultTableModel(new Object[] { "Evaluator", "Value" }, 0);
		
		tblEvaluator.setModel(tblEvaluatorModel);
		scrollPane_2.setViewportView(tblEvaluator);

		final JSplitPane splitPane_1 = new JSplitPane();
		splitPane_1.setDividerSize(4);
		splitPane_1.setResizeWeight(0.5);
		splitPane_1.setOrientation(JSplitPane.VERTICAL_SPLIT);
		panel_4.add(splitPane_1);
		springLayout_1.putConstraint(SpringLayout.EAST, splitPane_1, -11, SpringLayout.EAST, panel_4);
		springLayout_1.putConstraint(SpringLayout.WEST, splitPane_1, 0, SpringLayout.WEST, scrollPane_2);
		springLayout_1.putConstraint(SpringLayout.SOUTH, splitPane_1, -7, SpringLayout.SOUTH, panel_4);
		springLayout_1.putConstraint(SpringLayout.NORTH, splitPane_1, 5, SpringLayout.SOUTH, scrollPane_2);

		final JScrollPane scrollPane_3 = new JScrollPane();
		splitPane_1.setLeftComponent(scrollPane_3);

		txtSolution = new JTextArea();
		txtSolution.setFont(new Font("Courier New", Font.PLAIN, 12));
		scrollPane_3.setViewportView(txtSolution);

		simulationTimelinePanel = new SimulationTimelinePanel();
		splitPane_1.setRightComponent(simulationTimelinePanel);
		//
	}


	public void setupContext(IAppContext context) {
		Context = context;
	}
	
	@SuppressWarnings("unchecked")
	public void setupListener(MP_PlannerPanel panel) {
		panel.onPlanned.add(new Event<Object>() {
			@Override
			public void run(Object sender, Object arg) {
				planCompleted((MP_PlannerPanel) sender);
			}
		});

	}

	protected void planCompleted(MP_PlannerPanel panel) {
		lbSolutionModel.clear();
		solutions = panel.getSolutions();
		model = Context.getService(PddlModel.class);
		for (PddlSolution sol : solutions) {
			lbSolutionModel.addElement(sol.getName());
			for(PddlModel.Evaluator eval: model.Evaluators)
				solutionData.put(sol, new Object[] { eval.getName(), eval.getInstance().evaluate(Context, model, sol).getValue() });
		}
		
	}
	
	protected void updateSolutionListSelection() {
		int idx = lbSolutions.getSelectedIndex();
		tblEvaluatorModel.getDataVector().clear();
		if (idx >= 0 && solutions != null) {
			PddlSolution sol = solutions.get(idx);
			txtSolution.setText(sol.toString());
			tblEvaluatorModel.addRow(solutionData.get(sol));
			simulationTimelinePanel.setSolution(Context, model, sol);
		}
	}
}
